package framework.spatial;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;
import javax.swing.JPanel;

/**
 *
 * @author Lukáš Marek
 */
public class FRDSpatialMap extends JPanel implements MouseListener, MouseMotionListener
{
	protected FRDSpatialMapBackground back;
	protected FRDSpatialController controller;
	protected LinkedList<FRDSpatialGItem> objects = null;
	protected Point p1,p2,pBack;
	
	protected FRDSpatial parent = null;
	
	protected boolean edit = false;
	protected boolean mouseDown = false;
	
	protected FRDSpatialGItem newItem = null;
	public FRDSpatialGItem selectedItem = null;
	
	public FRDSpatialMap(FRDSpatial _parent)
	{
		parent = _parent;
	}
	
	/**
	 * nastavi objekt starajici se o pozadi a parametry s tim spojene
	 * @param back 
	 */
	public void setBackroundClass(FRDSpatialMapBackground back)
	{
		this.back = back;
		back.setWidth(getWidth());
		back.setHeight(getHeight());
		p1 = new Point();
		p2 = new Point();
		pBack = new Point();
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
	}
	
	/**
	 * Pridani noveho objektu
	 * @param n 
	 */
	public void addNewItem(FRDSpatialGItem n)
	{
		newItem = n;
		newItem.setBack(back);
		if (selectedItem != null) selectedItem.setSelected(false);
		controller.selectedItem(null);
		selectedItem = null;
		edit = false;
	}
	
	/**
	 * vykresleni pozadi a vsech objektu
	 * @param g 
	 */
	@Override
	public void paintComponent(Graphics g)
	{
		if (back != null)
		{
			back.paint(g);
			if (objects != null)
			{
				for (int i = 0; i < objects.size(); i++)
				{
					objects.get(i).draw(g);
				}
			}
			if (newItem != null)
			{
				if (mouseDown) newItem.setPoints(p1, p2);
				newItem.draw(g);
			}
			else if (selectedItem != null && edit && p1.distance(p2) > 3 && mouseDown)
			{
				selectedItem.drawEdit(g, p1, p2);
			}
		}
	}

	/**
	 * stisknuti tlacitka
	 * @param me 
	 */
	@Override
	public void mousePressed(MouseEvent me)
	{
		p1.setLocation(me.getPoint());
		p2.setLocation(me.getPoint());
		pBack.setLocation(back.getPosition());
		if (newItem != null) newItem.setPoints(p1, p2);
		mouseDown = true;
	}

	/**
	 * pusteni tlacitka
	 * @param me 
	 */
	@Override
	public void mouseReleased(MouseEvent me)
	{
		p2.setLocation(me.getPoint());
		if (newItem != null)
		{
			if (newItem.addPoints(p1, p2))
			{
				objects.add(newItem);
				((FRDSpatialModel)parent.getModel()).addItem(newItem);
				newItem = null;
				parent.endPaintButton.setVisible(false);
			}
			else
				parent.endPaintButton.setVisible(true);
		}
		else if (p1.distance(p2) < 3)
		{
			if (selectedItem != null)
			{
				selectedItem.setSelected(false);
				selectedItem = null;
				controller.selectedItem(null);
			}
			for (int i = objects.size() - 1; i >= 0; i--)
			{
				if (objects.get(i).undermouse(p1))
				{
					selectedItem = objects.get(i);
					controller.selectedItem(selectedItem);
					objects.get(i).setSelected(true);
					edit = true;
					break;
				}
			}
			if (selectedItem == null) edit = false;
		}
		else if (newItem == null && selectedItem == null)
		{
			double diff = back.getScale() / back.getZoom();
			back.setPosition(new Point(pBack.x + (int)((p1.x - p2.x) * diff), pBack.y + (int)((p1.y - p2.y) * diff)));
		}
		else
		{
			selectedItem.saveEdit(p1, p2);
			((FRDSpatialModel)parent.getModel()).editItem(selectedItem);
		}
		mouseDown = false;
		repaint();
	}
	
	/**
	 * posun mysi pri stisknutem tlacitku
	 * @param me 
	 */
	@Override
	public void mouseDragged(MouseEvent me)
	{
		p2.setLocation(me.getPoint());
		if (newItem == null && selectedItem == null)
		{
			double diff = back.getScale() / back.getZoom();
			back.setPosition(new Point(pBack.x + (int)((p1.x - p2.x) * diff), pBack.y + (int)((p1.y - p2.y) * diff)));
		}
		repaint();
	}

	@Override
	public void mouseEntered(MouseEvent me) {}

	@Override
	public void mouseExited(MouseEvent me) {}

	@Override
	public void mouseClicked(MouseEvent me) {}

	@Override
	public void mouseMoved(MouseEvent me) {}

	public void setData(LinkedList data)
	{
		objects = data;
	}

	/**
	 * ukonceni kresleni, pouze pro lomenou caru
	 */
	public void endPaint()
	{
		if (newItem != null)
		{
			objects.add(newItem);
			((FRDSpatialModel)parent.getModel()).addItem(newItem);
			newItem = null;
			parent.endPaintButton.setVisible(false);
		}
	}

	/**
	 * nastaveni kontroleru
	 * @param controller 
	 */
	public void setController(FRDSpatialController controller)
	{
		this.controller = controller;
	}
}
